import {Component, OnInit, SimpleChange, ViewChild} from '@angular/core';
import {DatePipe} from '@angular/common';
import {FarmService} from '../../../service/farm.service';
import {DataSourceService} from '../../../service/data-source/data-source.service';
import {Farm} from '../../../entity/farm.model';
import {FarmData} from './wind-direction-change/wind-direction.model';
import {TagData} from '../../../entity/tag-data.model';
import {List} from 'linqts';
import {ApplicationService} from '../../../service/application.service';
import {WindSpeedDistributionComponent} from './wind-speed-distribution/wind-speed-distribution.component';
import {WindDirectionComponent} from './wind-direction/wind-direction.component';
import {WindDirectionChangeComponent} from './wind-direction-change/wind-direction-change.component';
import {UltrashortForecastingPowerComponent} from './ultrashort-forecasting-power/ultrashort-forecasting-power.component';
import {InterceptorService} from '../../../service/interceptor/interceptor-service';

@Component({
  selector: 'app-wind-energy',
  templateUrl: './wind-energy.component.html',
  styleUrls: ['./wind-energy.component.css']
})
export class WindEnergyComponent implements OnInit {
  /**
   * 风场数据
   *
   * @type {LimitedFarmData[]}
   * @memberof WindEnergyComponent
   */
  limitedFarmDatas: LimitedFarmData[] = [];
  /**
   * 当前风场数据
   *
   * @type {LimitedFarmData}
   * @memberof WindEnergyComponent
   */
  currentlimitedFarm: LimitedFarmData;
  /**
   * 公司总数据
   *
   * @type {LimitedFarmData}
   * @memberof WindEnergyComponent
   */
  companylimite: LimitedFarmData;
  bladesindiameter: number = 82;
  startTime: Date;
  endTime: Date;
  cdcendTime: Date;
  cdcStartTime: Date;
  shortEndTime: Date;
  titleText = (new Date().getMonth() + 1) + '月';
  @ViewChild(WindSpeedDistributionComponent, {static: true})
  speedDistribution: WindSpeedDistributionComponent;
  @ViewChild(WindDirectionComponent, {static: true})
  windDirection: WindDirectionComponent;
  @ViewChild(WindDirectionChangeComponent, {static: true})
  windDirectionChange: WindDirectionChangeComponent;
  @ViewChild('dq', {static: true})
  dq: UltrashortForecastingPowerComponent;
  @ViewChild('cdq', {static: true})
  cdq: UltrashortForecastingPowerComponent;

  constructor(
    private datePipe: DatePipe,
    private farmService: FarmService,
    private dataSource: DataSourceService,
    private application: ApplicationService,
    private http: InterceptorService
  ) {
  }

  ngOnInit() {

    const farms = this.application.currentUserFarms.filter(farm => farm.farmCategory === 'winfarm');
    const items = farms.map(o => o.farmId);
    this.farmService.getFarmSweptDiameterByFarmId(items).then(res => {
      for (const t in res) {
        let i = farms.findIndex(o => o.farmId == parseInt(t));
        if (i > -1) {
          let num = this.bladesindiameter;
          if (res[t]) {
            num = res[t]['bladeSindiaMeter'] ? res[t]['bladeSindiaMeter'] : this.bladesindiameter;
          }
          farms[i].windEnergy = Math.pow(num / 2, 2) * Math.PI;
        }
      }
      this.createFarmModel(farms);
    }).catch(err => {
      console.log(err);
    })
  }

  public ngOnDestroy(): void {
    if (this.dataSource != null) {
      this.dataSource.dispose();
    }
  }

  createFarmModel(farms: Farm[]) {
    if (this.dataSource != null) {
      this.dataSource.dispose();
    }
    this.dataSource = new DataSourceService(this.http, this.datePipe);
    const date = new Date(),
      startTime = new Date(date.getFullYear(), date.getMonth()),
      //MeanWindSpeed = this.application.tagDict['MeanWindSpeed'],// 风速
      //AmbWindDir = this.application.tagDict['AmbWindDir'], // 风向
      CMeanWindSpeed = this.application.tagDict['CWindSpeed'], // 预测风速
      CAmbWindDir = this.application.tagDict['CAmbWindDir'], // 预测风向
      dq = this.application.tagDict['DQ001'], // 短期
      cdq = this.application.tagDict['CDQ001'], // 超短期
      ///Temperature = this.application.tagDict['Temperature'], // 温度
      Temp = this.application.tagDict['TEMPERATURE'],
      // AirPressure = this.application.tagDict['AirPressure'],//气压
      Humidity = this.application.tagDict['HUMIDITY'], // 湿度
      cDirectionCodes = [],
      codes = [], //风速，风向历史查询1个月的code
      dqCodes = [],
      cdqCodes = [],
      data: any[][][] = [],
      Minutes = (Math.floor((date.getMinutes()) / 15)) * 15;

    this.startTime = new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), Minutes);
    this.shortEndTime = new Date(this.startTime.getTime() + 1000 * 60 * 60 * 4);
    this.endTime = new Date(this.startTime.getTime() + 1000 * 60 * 60 * 72);
    this.cdcStartTime = new Date(this.startTime.getTime() - 1000 * 60 * 60 * 24);
    this.cdcendTime = this.startTime;
    this.companylimite = {
      farmName: '公司',
      farmId: 0,
      farmCode: '',
      windEnergy: farms[0].windEnergy,
      directionChange: {
        farmId: 0,
        farmName: '公司',
        temperature: [],//温度
        // airPressure?: TagData[],//气压
        humidity: [],//湿度
        ambWindDir: [],
        meanWindSpeed: []
      }
    };
    farms.forEach((farm, i) => {
      const farmCode = farm.farmCode.replace(/_1$/, '_3'),
        // MeanWindSpeedCode = this.dataSource.buildTagCode([farm.farmCode], CMeanWindSpeed),
        //AmbWindDirCode = this.dataSource.buildTagCode([farm.farmCode], CAmbWindDir),
        dqCode = this.dataSource.buildTagCode([farmCode], dq),
        cdqCode = this.dataSource.buildTagCode([farmCode], cdq),
        TemperatureCode = this.dataSource.buildTagCode([farm.farmCode, '4'], Temp),
        HumidityCode = this.dataSource.buildTagCode([farm.farmCode, '4'], Humidity),
        CMeanWindSpeedCode = this.dataSource.buildTagCode([farm.farmCode, '4'], CMeanWindSpeed),
        CAmbWindDirCode = this.dataSource.buildTagCode([farm.farmCode, '4'], CAmbWindDir);
      data.push([]);
      let limitedFarmData: LimitedFarmData = {
        farmId: farm.farmId,
        farmCode: farm.farmCode,
        farmName: farm.farmName,
        windEnergy: farm.windEnergy,
        unShowName: farm.unShowName,
        dqData: dqCode,
        cdqData: cdqCode,
        windSpeed: CMeanWindSpeedCode,
        ambWindDir: CAmbWindDirCode,
        cMeanWindSpeed: CMeanWindSpeedCode,
        cdqSeries: [],
        dqSeries: [],
        speedDistribution: [],
        windDirectionData: [],
        windEnergySeriesData: [],
        cAmbWindDir: CAmbWindDirCode,
        temperature: TemperatureCode,
        humidity: HumidityCode,
        windDirectionReal: this.dataSource.binding([farm.farmCode, '4'], CAmbWindDir),
        temperatureReal: this.dataSource.binding([farm.farmCode, '4'], Temp),
        windSpeedReal: this.dataSource.binding([farm.farmCode, '4'], CMeanWindSpeed),
        posx: farm.posx,
        posy: farm.posy,
        directionChange: {
          farmId: farm.farmId,
          farmName: farm.farmName,
          temperature: [],//温度
          // airPressure?: TagData[],//气压
          humidity: [],//湿度
          ambWindDir: [],
          meanWindSpeed: []
        }
      };
      this.limitedFarmDatas.push(limitedFarmData);
      codes.push(CMeanWindSpeedCode, CAmbWindDirCode);
      dqCodes.push(dqCode);
      cdqCodes.push(cdqCode);
      cDirectionCodes.push(CMeanWindSpeedCode, CAmbWindDirCode, TemperatureCode, HumidityCode);
    });

    //this.currentlimitedFarm = this.companylimite;
    //this.farmDatas = farmDatas;
    //地图实时数据
    this.dataSource.begin().subscribe(next => {
    }, error => {
      console.log('app-main createLimitedFarm has error', error);
    });
    const day = new Date().getDate();
    const tagNum = day * this.limitedFarmDatas.length;
    let inter = 1800;
    if (tagNum > 30 && tagNum <= 50) {
      inter = 1800 * 2;
    } else if (tagNum > 50 && tagNum <= 100) {
      inter = 1800 * 4;
    } else if (tagNum > 100 && tagNum <= 150) {
      inter = 1800 * 6;
    } else if (tagNum > 150) {
      inter = 1800 * 8;
    }
    this.dataSource.history.getHistories(codes, startTime, this.startTime, inter).then(res => {
      if (!res) return false;
      const ambWindDir = res.filter(o => o.code.endsWith(CAmbWindDir.tagCode)),
        windSpeed = res.filter(o => o.code.endsWith(CMeanWindSpeed.tagCode));
      this.getWindEnergy(this.companylimite, ambWindDir, windSpeed);
      this.limitedFarmDatas.forEach(limitedFarm => {
        // tslint:disable-next-line:no-shadowed-variable
        const ambWindDir = res.filter(tagData => tagData.code === limitedFarm.ambWindDir),
          // tslint:disable-next-line:no-shadowed-variable
          windSpeed = res.filter(tagData => tagData.code === limitedFarm.windSpeed);
        this.getWindEnergy(limitedFarm, ambWindDir, windSpeed);
      });
      this.speedDistribution.ngOnChanges({
        'seriesData': new SimpleChange(this.speedDistribution.seriesData, this.currentlimitedFarm.speedDistribution, false)
      });
      this.windDirection.ngOnChanges({
        'seriesData': new SimpleChange(this.windDirection.seriesData, this.currentlimitedFarm.windDirectionData, false),
        'windEnergySeriesData': new SimpleChange(this.windDirection.windEnergySeriesData, this.currentlimitedFarm.windEnergySeriesData, false),
      });
    }).catch(err => {
      console.log(err);
    });
    this.dataSource.history.getHistories(dqCodes, this.startTime, this.endTime, 900).then(res => {
      if (!res) {
        return false;
      }
      this.limitedFarmDatas.forEach(limitedFarmData => {
        const dqData = res.filter(tagData => tagData.code === limitedFarmData.dqData);
        this.getDqseries(limitedFarmData, dqData);
      });
      this.getDqseries(this.companylimite, res);
      this.dq.ngOnChanges({
        'seriesDatas': new SimpleChange(this.dq.seriesDatas, this.currentlimitedFarm.dqSeries, false)
      });
    }).catch(err => {
      console.log('wind-energy' + err);
    })
    this.dataSource.history.getHistories(cdqCodes, this.startTime, this.shortEndTime, 900).then(res => {
      if (!res) {
        return false;
      }
      this.limitedFarmDatas.forEach(limitedFarmData => {
        const cdqData = res.filter(tagData => tagData.code === limitedFarmData.cdqData);
        this.getCdqseries(limitedFarmData, cdqData);
      });
      this.getCdqseries(this.companylimite, res);
      this.cdq.ngOnChanges({
        'seriesDatas': new SimpleChange(this.cdq.seriesDatas, this.currentlimitedFarm.cdqSeries, false)
      });
    }).catch(err => {
      console.log('wind-energy' + err);
    });
    this.dataSource.history.getHistories(cDirectionCodes, this.cdcStartTime, this.cdcendTime, 900).then(res => {
      if (!res) return false;
      let totalAmbWindDir: TagData[] = [],
        totalHumidity = [],
        totalTemperature = [],
        totalMeanWindSpeed = [];
      this.limitedFarmDatas.forEach(limitedFarmData => {
        const ambWindDir = res.filter(o => o.code === limitedFarmData.cAmbWindDir),
          humidity = res.filter(o => o.code === limitedFarmData.humidity),
          temperature = res.filter(o => o.code === limitedFarmData.temperature),
          meanWindSpeed = res.filter(o => o.code === limitedFarmData.cMeanWindSpeed);
        limitedFarmData.directionChange.ambWindDir = ambWindDir;
        limitedFarmData.directionChange.humidity = humidity;
        limitedFarmData.directionChange.temperature = temperature;
        limitedFarmData.directionChange.meanWindSpeed = meanWindSpeed;
        if (!totalAmbWindDir.length) {
          ambWindDir.forEach(tagData => {
            let obj = {
              code: '',
              time: tagData.time,
              value: tagData.value
            };
            totalAmbWindDir.push(obj)
          });
        } else {
          ambWindDir.forEach(windDir => {
            const index = totalAmbWindDir.findIndex(o => new Date(o.time).getTime() === new Date(windDir.time).getTime());
            if (index >= 0) {
              totalAmbWindDir[index].value = Number(windDir.value) + Number(totalAmbWindDir[index].value);
            }
          });
        }
        if (!totalHumidity.length) {
          humidity.forEach(tagData => {
            let obj = {
              code: '',
              time: tagData.time,
              value: tagData.value
            };
            totalHumidity.push(obj);
          });
          //totalHumidity = humidity.slice(0);
        } else {
          humidity.forEach(hum => {
            const index = totalHumidity.findIndex(o => new Date(o.time).getTime() === new Date(hum.time).getTime());
            if (index >= 0) {
              totalHumidity[index].value = Number(hum.value) + Number(totalHumidity[index].value);
            }
          });
        }
        if (!totalTemperature.length) {
          temperature.forEach(tagData => {
            let obj = {
              code: '',
              time: tagData.time,
              value: tagData.value
            };
            totalTemperature.push(obj);
          });
          //totalTemperature = temperature.slice(0);
        } else {
          temperature.forEach(temper => {
            const index = totalTemperature.findIndex(o => new Date(o.time).getTime() === new Date(temper.time).getTime());
            if (index >= 0) {
              totalTemperature[index].value = Number(temper.value) + Number(totalTemperature[index].value);
            }
          });
        }
        if (!totalMeanWindSpeed.length) {
          meanWindSpeed.forEach(tagData => {
            let obj = {
              code: '',
              time: tagData.time,
              value: tagData.value
            };
            totalMeanWindSpeed.push(obj);
          });
          //totalMeanWindSpeed = meanWindSpeed.slice(0);
        } else {
          meanWindSpeed.forEach(WindSpeed => {
            const index = totalMeanWindSpeed.findIndex(o => new Date(o.time).getTime() === new Date(WindSpeed.time).getTime());
            if (index >= 0) {
              totalMeanWindSpeed[index].value = Number(WindSpeed.value) + Number(totalMeanWindSpeed[index].value);
            }
          });
        }
      });

      const len = this.limitedFarmDatas.length;
      totalAmbWindDir.map(o => {
        return o.value = parseFloat((Number(o.value) / len).toFixed(2));
      });
      totalHumidity.map(o => {
        return o.value = parseFloat((Number(o.value) / len).toFixed(2));
      });
      totalTemperature.map(o => {
        return o.value = parseFloat((Number(o.value) / len).toFixed(2));
      });
      totalMeanWindSpeed.map(o => {
        return o.value = parseFloat((Number(o.value) / len).toFixed(2));
      });
      this.companylimite.directionChange.ambWindDir = totalAmbWindDir;
      this.companylimite.directionChange.humidity = totalHumidity;
      this.companylimite.directionChange.temperature = totalTemperature;
      this.companylimite.directionChange.meanWindSpeed = totalMeanWindSpeed;
      this.windDirectionChange.ngOnChanges({
        'currentFarm': new SimpleChange(this.windDirectionChange.currentFarm, this.currentlimitedFarm.directionChange, false)
      });
    }).catch(err => {
      console.log(err);
    });
    this.currentlimitedFarm = this.companylimite;
  }

  getWindEnergy(limitedFarm: LimitedFarmData, ambWindDir: TagData[], windSpeed: TagData[]) {//玫瑰图，分布概率图
    let tagDataSeries: CodeData[][] = [];
    let data: Data = {};
    ['W', 'WSW', 'SW', 'SSW', 'S', 'SSE', 'SE', 'ESE', 'E', 'ENE', 'NE', 'NNE', 'N', 'NNW', 'NW', 'WNW'].forEach((v, i) => {
      tagDataSeries.push([]);
    });
    for (let i = 0; i < 25; i++) {
      data[i + 1] = 0;
    }
    windSpeed.forEach((o) => {
      let value = Math.round(o.value);
      if (data[value] || data[value] === 0) {
        data[value] = data[value] + 1;
      }
    })
    let total = 0;
    for (const t in data) {
      total += data[t];
    }
    let seriesData: number[][] = [];
    for (const t in data) {
      seriesData.push([parseFloat(t), total ? parseFloat((data[t] / total * 100).toFixed(2)) : 0]);
    }
    limitedFarm.speedDistribution = seriesData;
    // 风向数据
    let driecData = ambWindDir;
    let speedData = windSpeed;
    let codeDatas: CodeData[] = [];
    driecData.forEach(data => {
      if (data.value < 0) {
        return false;
      }
      let index = speedData.findIndex(o => new Date(o.time).getTime() == new Date(data.time).getTime());
      if (index > -1) {
        let obj: CodeData = {
          time: data.time,
          driectionValue: data.value,
          speedValue: speedData[index].value,
          windEnergy: Math.pow(speedData[index].value, 3) * limitedFarm.windEnergy
        };
        codeDatas.push(obj);
        let dis = 360 / 16 / 2;
        if (data.value <= dis * 1 || data.value > dis * 31) {
          tagDataSeries[0].push(obj);
        } else if (data.value >= dis * 1 && data.value < dis * 3) {
          tagDataSeries[15].push(obj);
        } else if (data.value >= dis * 3 && data.value < dis * 5) {
          tagDataSeries[14].push(obj);
        } else if (data.value >= dis * 5 && data.value < dis * 7) {
          tagDataSeries[13].push(obj);
        } else if (data.value >= dis * 7 && data.value < dis * 9) {
          tagDataSeries[12].push(obj);
        } else if (data.value >= dis * 9 && data.value < dis * 11) {
          tagDataSeries[11].push(obj);
        } else if (data.value >= dis * 11 && data.value < dis * 13) {
          tagDataSeries[10].push(obj);
        } else if (data.value >= dis * 13 && data.value < dis * 15) {
          tagDataSeries[9].push(obj);
        } else if (data.value >= dis * 15 && data.value < dis * 17) {
          tagDataSeries[8].push(obj);
        } else if (data.value >= dis * 17 && data.value < dis * 19) {
          tagDataSeries[7].push(obj);
        } else if (data.value >= dis * 19 && data.value < dis * 21) {
          tagDataSeries[6].push(obj);
        } else if (data.value >= dis * 21 && data.value < dis * 23) {
          tagDataSeries[5].push(obj);
        } else if (data.value >= dis * 23 && data.value < dis * 25) {
          tagDataSeries[4].push(obj);
        } else if (data.value >= dis * 25 && data.value < dis * 27) {
          tagDataSeries[3].push(obj);
        } else if (data.value >= dis * 27 && data.value < dis * 29) {
          tagDataSeries[2].push(obj);
        } else if (data.value >= dis * 29 && data.value < dis * 31) {
          tagDataSeries[1].push(obj);
        }
      }
    });
    limitedFarm.windRose = codeDatas;
    limitedFarm.windDirectionData = [];
    limitedFarm.windEnergySeriesData = [];
    let totalDir = 0;
    let totalWindEnergy = 0;
    tagDataSeries.forEach((v, i) => {
      totalDir += v.length;
      limitedFarm.windDirectionData[i] = v.length;
      v.forEach(windEnergy => {
        totalWindEnergy += windEnergy.windEnergy;
      });
      if (v.length) {
        let vData = new List(v);
        let sum = vData.Sum(o => o.windEnergy);
        limitedFarm.windEnergySeriesData[i] = sum;
      } else {
        limitedFarm.windEnergySeriesData[i] = 0;
      }
    });
    if (totalDir) {
      limitedFarm.windDirectionData = limitedFarm.windDirectionData.map(o => parseFloat((o / totalDir * 100).toFixed(2)));
    }
    // 风能数据
    if (totalWindEnergy) {
      limitedFarm.windEnergySeriesData = limitedFarm.windEnergySeriesData.map(o => parseFloat((o / totalWindEnergy * 100).toFixed(2)));
    }
  }

  getDqseries(limitedFarmData: LimitedFarmData, dqData: TagData[]) {
    let resList = new List(dqData);
    let tagDates = resList.GroupBy(grouper => grouper.time, mapper => mapper);
    let tagTimes = Object.getOwnPropertyNames(tagDates);
    let seriesData: any[][] = [];
    tagTimes.forEach((tagData) => {
      let value = 0;
      tagDates[tagData].forEach(v => {
        value += v.value;
      });
      let timeData = [new Date(tagData), parseFloat(value.toFixed(2))];
      seriesData.push(timeData);
    });
    limitedFarmData.dqSeries = seriesData;
  }

  getCdqseries(limitedFarmData: LimitedFarmData, cdqData: TagData[]) {
    let resList = new List(cdqData);
    let tagDates = resList.GroupBy(grouper => grouper.time, mapper => mapper);
    let tagTimes = Object.getOwnPropertyNames(tagDates);
    let seriesData: any[][] = [];
    tagTimes.forEach((tagData) => {
      let value = 0;
      tagDates[tagData].forEach(v => {
        value += v.value;
      })
      let timeData = [new Date(tagData), parseFloat(value.toFixed(2))];
      seriesData.push(timeData);
    })
    limitedFarmData.cdqSeries = seriesData;
  }

  onfarmChange(ev: number) {
    if (ev === null) {
      this.currentlimitedFarm = this.companylimite;
    } else {
      this.currentlimitedFarm = this.limitedFarmDatas[ev];
    }
    this.dq.ngOnChanges({
      'seriesDatas': new SimpleChange(this.dq.seriesDatas, this.currentlimitedFarm.dqSeries, false)
    });
    this.windDirectionChange.ngOnChanges({
      'currentFarm': new SimpleChange(this.windDirectionChange.currentFarm, this.currentlimitedFarm.directionChange, false)
    });
    this.cdq.ngOnChanges({
      'seriesDatas': new SimpleChange(this.cdq.seriesDatas, this.currentlimitedFarm.cdqSeries, false)
    });
    this.speedDistribution.ngOnChanges({
      'seriesData': new SimpleChange(this.speedDistribution.seriesData, this.currentlimitedFarm.speedDistribution, false)
    });
    this.windDirection.ngOnChanges({
      'seriesData': new SimpleChange(this.windDirection.seriesData, this.currentlimitedFarm.windDirectionData, false),
      'windEnergySeriesData': new SimpleChange(this.windDirection.windEnergySeriesData, this.currentlimitedFarm.windEnergySeriesData, false),
    });
  }
}

interface Data {
  [index: number]: number;
}

interface CodeData {
  time: Date;
  driectionValue: number;
  speedValue: number;
  windEnergy: number;
}

export interface LimitedFarmData {
  farmId: number;
  farmName: string;
  farmCode: string;
  windEnergy: number,
  unShowName?: boolean,
  dqData?: string;
  cdqData?: string;
  windSpeed?: string;
  windRose?: CodeData[];
  ambWindDir?: string;
  cMeanWindSpeed?: string;
  cAmbWindDir?: string;
  temperature?: string;
  humidity?: string;
  speedDistribution?: number[][];
  windDirectionData?: number[];
  windEnergySeriesData?: number[];
  windDirectionReal?: TagData;
  temperatureReal?: TagData;
  windSpeedReal?: TagData;
  directionChange?: FarmData;
  dqSeries?: any[][];
  cdqSeries?: any[][];
  posx?: number;
  posy?: number;
}

interface CodeDatas {
  code: string;
  data?: TagData[];
}
